# **************************************
# --*-- coding: utf-8 --*--
# @Author  : white
# @FileName: mian.py
# @Time    : 2025-09-05
# **************************************
import numpy as np  # 导入NumPy库，用于数组操作

# 生成数据集：2个类别，每个类别100个样本
# 类别0：均值为[2, 2]，标准差为1的高斯分布
# 类别1：均值为[6, 6]，标准差为1的高斯分布
num_samples = 100  # 每个类别的样本数
X_class0 = np.random.normal(loc=2, scale=1, size=(num_samples, 2))  # 生成类别0的特征数据
y_class0 = np.zeros(num_samples)  # 类别0的标签为0
X_class1 = np.random.normal(loc=6, scale=1, size=(num_samples, 2))  # 生成类别1的特征数据
y_class1 = np.ones(num_samples)  # 类别1的标签为1

X = np.vstack((X_class0, X_class1))  # 垂直堆叠特征数据，形成总特征矩阵 (200, 2)
y = np.hstack((y_class0, y_class1))  # 水平堆叠标签，形成总标签数组 (200,)

# 添加偏置项：在X左侧添加一列全1，用于偏置b
X = np.hstack((np.ones((X.shape[0], 1)), X))  # X形状变为 (200, 3)


# 定义Sigmoid函数：将线性输出映射到[0,1]
def sigmoid(z):
    return 1 / (1 + np.exp(-z))  # Sigmoid公式


# 定义损失函数：二元交叉熵损失
def compute_loss(y_true, y_pred):
    epsilon = 1e-9  # 防止log(0)导致的数值问题
    loss = -np.mean(y_true * np.log(y_pred + epsilon) + (1 - y_true) * np.log(1 - y_pred + epsilon))  # 计算平均损失
    return loss


# 初始化参数：权重w和偏置b（包含在theta中）
theta = np.random.randn(X.shape[1])  # theta形状 (3,)，随机初始化

# 设置超参数
learning_rate = 0.01  # 学习率
num_epochs = 1000  # 迭代次数

# 训练过程：梯度下降
for epoch in range(num_epochs):
    # 前向传播：计算线性组合和Sigmoid预测
    z = np.dot(X, theta)  # z = X * theta
    y_pred = sigmoid(z)  # 预测概率

    # 计算梯度：损失对theta的导数
    gradient = np.dot(X.T, (y_pred - y)) / len(y)  # 梯度公式：(1/m) * X^T * (y_pred - y)

    # 更新参数
    theta -= learning_rate * gradient  # theta = theta - alpha * gradient

    # 每100次迭代打印损失（可选监控）
    if epoch % 100 == 0:
        loss = compute_loss(y, y_pred)
        print(f"Epoch {epoch}: Loss = {loss:.4f}")


# 预测函数：对新数据进行分类
def predict(X_new):
    X_new = np.hstack((np.ones((X_new.shape[0], 1)), X_new))  # 添加偏置项
    z = np.dot(X_new, theta)  # 计算线性组合
    y_pred_prob = sigmoid(z)  # 计算概率
    return (y_pred_prob >= 0.5).astype(int)  # 大于0.5分类为1，否则0


# 测试：使用原始数据的前5个样本进行预测
test_samples = X[:5, 1:]  # 取前5个样本的特征（去除偏置列）
predictions = predict(test_samples)
print("前5个样本的预测结果:", predictions)
